package aml.runtime;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

abstract public class Value implements Cloneable {
	
	protected Map<String, Value> slots = new HashMap<String, Value>();
	
	public Value clone() {
		Value cloned = null;
		try {
			cloned = (Value) super.clone();
			cloned.slots = new HashMap<String, Value>();
			Set<String> slotNames = slots.keySet();
			Iterator<String> it = slotNames.iterator();
			while (it.hasNext()) {
				String slotName = it.next();
				cloned.slots.put(slotName, slots.get(slotName));
			}
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cloned;
	}

	public Value call(Context ctx, String slotName, Value[] args) {
		Value slot = getSlot(slotName);
		if (slot instanceof Method) {
			return ((Method) slot).apply(ctx, args);
		}
		return null;
	}
	
	public Value getSlot(String slotName) {
		return slots.get(slotName);
	}
	
	public Value setSlot(String slotName, Value slot) {
		return slots.put(slotName, slot);
	}

	abstract public ValueNum toNum();
	
	public String toString() {
		Set<String> slotNames = slots.keySet();
		Iterator<String> it = slotNames.iterator();
		StringBuilder sb = new StringBuilder();
		sb.append("{ ");
		while (it.hasNext()) {
			String slotName = it.next();
			sb.append(slotName).append(":").append(getSlot(slotName)).append(" ");
		}
		sb.append("}");
		return sb.toString();
	}
}